package com.zbowen.juc.queen;

import com.zbowen.juc.ReentrantLockDemo;
import com.zbowen.juc.utils.CarPlateNumberGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class CustomerDemo {

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomerDemo.class);
    private static final Random RAND = new Random();
    private static final SimpleDateFormat SDF = new SimpleDateFormat("HH:mm:ss.SSS");
    public static void main(String[] args) throws InterruptedException {
        List<Thread> list = new ArrayList<>();
        // 假设停车场只有10个车位
        FairSpinLock semaphore = new FairSpinLock();
        // 有10辆车要去停车场
        for (int i = 1; i < 30; i++) {
            Thread thread = new Thread(new CustomerDemo.Car(CarPlateNumberGenerator.generateCarPlateNumber(), semaphore), "线程" + (9+i));
            list.add(thread);
            TimeUnit.SECONDS.sleep(RAND.nextInt(3) + 1);
            thread.start();
        }
        for (Thread thread : list) {
            thread.join();
        }
    }

    static class Car implements Runnable {

        private String carId;
        private FairSpinLock fairSpinLock;

        public Car(String carId, FairSpinLock fairSpinLock) {
            this.carId = carId;
            this.fairSpinLock = fairSpinLock;
        }

        @Override
        public void run() {
            long begin = System.currentTimeMillis();
            LOGGER.info("[{}]准备进入停车场。", carId);
            try {
                // 获取锁
                fairSpinLock.lock(5, TimeUnit.SECONDS);
                // 生成随机停车时长
                int waitTime = RAND.nextInt(20) + 10;
                // 如果获取成功则打印
                LOGGER.info("[{}]成功进入停车场，预计停车[{}]秒。", carId, waitTime);
                TimeUnit.SECONDS.sleep(waitTime);
            } catch (InterruptedException e) {
                // 获取锁失败
                LOGGER.info("[{}]等待超时，气愤驱车离开！等等开始时间：[{}]", carId, SDF.format(new Date(begin)));
            } finally {
                LOGGER.info("[{}]离开停车场。", carId);
                fairSpinLock.unlock();
            }

        }
    }
}
